﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Attacker : MonoBehaviour 
{
	private Skills skills;
	[HideInInspector]public Gear gear;
	private LifeController target;
	private float lastAttackTime;
	private Animator anim;
	private PhotonView photView;
	private MotionController controller;
	[HideInInspector]public bool attacking;
	[HideInInspector] public bool midAttack;
	private TeamAble teamAble;
	private Collider col;
	public Transform rangedAttackOrigin;
	void Awake()
	{	
		teamAble = GetComponent<TeamAble>();
		controller = GetComponent<MotionController>();
		photView = PhotonView.Get (this);
		anim = this.GetComponent<Animator> ();
		lastAttackTime = Time.time;
		gear = this.GetComponent<Gear> ();
		skills = this.GetComponent<Skills> ();
		attacking = false;
		midAttack = false;
		if (rangedAttackOrigin == null)
		{
			rangedAttackOrigin = transform;
		}
	}
	void FixedUpdate()
	{	
		if (attacking && !midAttack)
		{
			if (!ValidTarget())
			{
				controller.StopAttacking();
			} else
			{	
				TryToAttack();
			}
		}
	}

		
	public void TryToAttack()
	{	
		if (Time.time > (lastAttackTime + gear.weapon.attackTime) && !midAttack && TargetInRange() && controller.lifeController.LocalIsOwner())
		{		
			Attack();
			photView.RPC ("Animate", PhotonTargets.All, gear.weapon.animName);
		}
	}
		void Attack()
	{	
		midAttack = true;
		controller.LookAt (target.transform.position);
		lastAttackTime = Time.time;
		StartCoroutine(WaitThenDamage());
		StartCoroutine(WaitForNextAttack());
		
	}

	IEnumerator WaitThenDamage()
	{
		yield return new WaitForSeconds(gear.weapon.animTime);
		if (ValidTarget())
		{	
			int amount = Roll();
			target.TakeDamage (amount, photView.viewID);
		} else
		{
			controller.StopAttacking();
		}
	}
	IEnumerator WaitForNextAttack()
	{
		yield return new WaitForSeconds(gear.weapon.attackTime);
		midAttack = false;
	}
	private bool ValidTarget()
	{
		return (target != null && target.avatar.activeSelf && target.teamAble.team != teamAble.team && target.teamAble.team != 3);
	}
	public bool TargetInRange()
	{	
		if (!ValidTarget())
		{
			return false;
		} else
		{	
			switch(gear.weapon.type)
			{
				case Weapon.Type.melee:
				{	
					return (controller.agent.remainingDistance<=gear.weapon.attackRange && !controller.agent.pathPending);
				}
				case Weapon.Type.ranged:
				{	
					return ClearLineOfSight() && GameFunctions.PlanarDistanceBetween(rangedAttackOrigin.position,target.col.ClosestPoint(rangedAttackOrigin.position))<gear.weapon.attackRange;
				}
			}
			return false;
		}	
	}
	bool ClearLineOfSight()
	{
		RaycastHit hit;
		if(Physics.Raycast(rangedAttackOrigin.position,target.col.ClosestPoint(rangedAttackOrigin.position)-rangedAttackOrigin.position,out hit))
		{	
			if (hit.transform.root == target.transform)
			{
				return true;
			} else
			{
				return false;
			}
		} else
		{	
			Debug.Log("Ray does not point toward target, or target does not have collider");
			return false;
		}
	}

	float DistanceToTarget()
	{
		Vector3 closestPoint =  target.col.ClosestPoint(transform.position);
		return GameFunctions.PlanarDistanceBetween (this.transform.position, closestPoint);
	}
		public void Target(LifeController lc)
	{
		target = lc;
		attacking = true;
	}

	public void Relax()
	{
		target = null;
		attacking = false;
	}

	public int Roll()
	{
		return 1;
	}

	[PunRPC]
	public void Animate(string animName)
	{	if (anim != null)
		{
		anim.Play (animName);
		}
	}

}
